package com.liuxinlong.modules.material.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelImportCallBack;
import com.liuxinlong.common.ExcelImportService;
import com.liuxinlong.common.ImportResp;
import com.liuxinlong.common.RowError;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.constant.RegionConstants;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.constant.TimeFormatConstants;
import com.liuxinlong.enums.MaterialResumeTypeEnum;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.dao.MaterialDao;
import com.liuxinlong.modules.dao.MaterialReplaceDao;
import com.liuxinlong.modules.dao.MaterialResumeDao;
import com.liuxinlong.modules.entity.MaterialReplace;
import com.liuxinlong.modules.entity.MaterialResume;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.modules.material.dto.MaterialReplaceImportDto;
import com.liuxinlong.modules.material.service.MaterialReplaceService;
import com.liuxinlong.modules.sync.service.SyncService;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.ThreadlocalUtils;
import com.liuxinlong.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 物料替换服务层实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2022年3月21日
 */
@Service
@Slf4j
public class MaterialReplaceServiceImpl implements MaterialReplaceService {

    @Autowired
    private MaterialReplaceDao materialReplaceDao;

    @Autowired
    private MaterialResumeDao materialResumeDao;

    @Autowired
    private MaterialDao materialDao;

    @Autowired
    private ExcelImportService excelImportService;

    @Autowired
    private SyncService syncService;

    @Override
    public List<Map<String, Object>> pageReplaceInfo(Map<String, Object> queryParam) {
        List<MaterialReplace> originList = materialReplaceDao.pageReplaceList(queryParam);
        int startNum = (int) queryParam.get("startNum");
        List<Map<String, Object>> resultList = completeResult(originList, startNum);
        return resultList;
    }

    @Override
    public int getReplaceCount(Map<String, Object> queryParam) {
        return materialReplaceDao.getReplaceCount(queryParam);
    }

    @Override
    public void addReplaceInfo(MaterialReplace materialReplace) {
        String id = SnowFlake.nextIdStr();
        materialReplace.setId(id);
        MaterialReplace mp = materialReplaceDao.selectOneByParam(materialReplace.getTargetMaterial(),
                materialReplace.getReplaceMaterial(), materialReplace.getRegion());
        if (!ObjectUtils.isEmpty(mp)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "已存在相同替换记录");
        }
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String targetMaterial = materialReplace.getTargetMaterial();
        String replaceTime = materialReplace.getReplaceTime();
        if (targetMaterial.contains(",")) {
            String[] materials = targetMaterial.trim().split(",");
            List<MaterialResume> mrList = new ArrayList<>(materials.length);
            for (String materialNo : materials) {
                MaterialResume mr = new MaterialResume();
                mr.setId(SnowFlake.nextIdStr());
                mr.setSourceId(id);
                mr.setMaterialNo(materialNo);
                mr.setOperateUser(currentUser.getId());
                mr.setOperateType(MaterialResumeTypeEnum.REPLACE_CHANGE.getValue());
                mr.setOperateTime(replaceTime);
                mr.setContent("物料替换");
                mr.setRegion(materialReplace.getRegion());
                mrList.add(mr);
            }
            materialResumeDao.batchAddResume(mrList);
        } else {
            MaterialResume mr = new MaterialResume();
            mr.setId(SnowFlake.nextIdStr());
            mr.setSourceId(id);
            mr.setMaterialNo(targetMaterial);
            mr.setOperateUser(currentUser.getId());
            mr.setOperateType(MaterialResumeTypeEnum.REPLACE_CHANGE.getValue());
            mr.setOperateTime(replaceTime);
            mr.setContent("物料替换");
            mr.setRegion(materialReplace.getRegion());
            materialResumeDao.addResume(mr);
        }
        materialReplaceDao.insert(materialReplace);
    }

    @Override
    public void updateReplaceInfo(MaterialReplace materialReplace) {
        String id = materialReplace.getId();
        MaterialReplace mp = materialReplaceDao.selectOneByParam(materialReplace.getTargetMaterial(),
                materialReplace.getReplaceMaterial(), materialReplace.getRegion());
        if (!ObjectUtils.isEmpty(mp) && !StringUtils.equals(mp.getId(),id)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "已存在相同替换记录");
        }
        MaterialReplace oldMp = materialReplaceDao.selectById(id);
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        String replaceTime = materialReplace.getReplaceTime();
        String oldTarget = oldMp.getTargetMaterial();
        String targetMaterial = materialReplace.getTargetMaterial();
        String oldReplace = oldMp.getReplaceMaterial();
        String replaceMaterial = materialReplace.getReplaceMaterial();
        if (!StringUtils.equals(oldTarget,targetMaterial) || !StringUtils.equals(oldReplace,replaceMaterial) ) {
            if (targetMaterial.contains(",")) {
               throw new AosException(ReturnCodes.HTTP_SYSTEM_ERROR,"修改异常，不支持批量修改");
            } else {
                MaterialResume mr = materialResumeDao.getMaterialResumeBySource(id);
                mr.setMaterialNo(targetMaterial);
                mr.setRegion(materialReplace.getRegion());
                mr.setOperateTime(replaceTime);
                mr.setOperateUser(currentUser.getId());
                materialResumeDao.updateById(mr);
            }
        }

        materialReplaceDao.updateById(materialReplace);
    }

    @Transactional
    @Override
    public void deleteReplaceInfo(String id) {
        MaterialReplace materialReplace = materialReplaceDao.selectById(id);
        if(ObjectUtils.isEmpty(materialReplace)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR,"删除物料替换记录失败，替换记录不存在！");
        }
        String targetMaterial = materialReplace.getTargetMaterial();
        String replaceTime  = materialReplace.getReplaceTime();
        String region = materialReplace.getRegion();
        if (targetMaterial.contains(",")) {
            String[] materials = targetMaterial.trim().split(",");
            materialResumeDao.deleteBatchResumeByMaterial(Arrays.asList(materials),region,replaceTime);
        } else {
            List<String> materialList = new ArrayList<>();
            materialList.add(targetMaterial);
            materialResumeDao.deleteBatchResumeByMaterial(materialList,region,replaceTime);
        }
        materialReplaceDao.deleteById(id);
    }

    @Override
    @Transactional
    public ImportResp batchAddReplace(List<MaterialReplaceImportDto> dataList) {
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        List<MaterialResume> resumeList = new ArrayList<>();
        List<MaterialReplace> replaceList = new ArrayList<>();
        List<Map> failedList = new ArrayList<>();
        int sort = 1;
        for (MaterialReplaceImportDto materialReplaceDto : dataList) {
            if (StringUtils.isNotEmpty(materialReplaceDto.getRegionOne())) {
                MaterialReplace mp = materialReplaceDao.selectOneByParam(materialReplaceDto.getTargetMaterial(),
                        materialReplaceDto.getReplaceMaterial(), RegionConstants.WPCNJ);
                if (!ObjectUtils.isEmpty(mp)) {
                    Map map = ObjectUtils.object2Map(materialReplaceDto);
                    map.put("sort", sort);
                    map.put("message", "已存在替换记录");
                    sort++;
                    failedList.add(map);
                    continue;
                }
            }
            if (StringUtils.isNotEmpty(materialReplaceDto.getRegionTwo())) {
                MaterialReplace mp = materialReplaceDao.selectOneByParam(materialReplaceDto.getTargetMaterial(),
                        materialReplaceDto.getReplaceMaterial(), RegionConstants.WSCNJ);
                if (!ObjectUtils.isEmpty(mp)) {
                    Map map = ObjectUtils.object2Map(materialReplaceDto);
                    map.put("sort", sort);
                    map.put("message", "已存在替换记录");
                    sort++;
                    failedList.add(map);
                    continue;
                }
            }
            if (StringUtils.isNotEmpty(materialReplaceDto.getRegionThree())) {
                MaterialReplace mp = materialReplaceDao.selectOneByParam(materialReplaceDto.getTargetMaterial(),
                        materialReplaceDto.getReplaceMaterial(), RegionConstants.WSCNJ);
                if (!ObjectUtils.isEmpty(mp)) {
                    Map map = ObjectUtils.object2Map(materialReplaceDto);
                    map.put("sort", sort);
                    map.put("message", "已存在替换记录");
                    sort++;
                    failedList.add(map);
                    continue;
                }
            }
            if (StringUtils.isNotEmpty(materialReplaceDto.getRegionOne())) {
                MaterialReplace materialReplace = completeEntryReplaceData(materialReplaceDto, RegionConstants.WPCNJ);
                replaceList.add(materialReplace);
                completeEntryResumeData(materialReplace, resumeList, currentUser, RegionConstants.WPCNJ);
            }
            if (StringUtils.isNotEmpty(materialReplaceDto.getRegionTwo())) {
                MaterialReplace materialReplace = completeEntryReplaceData(materialReplaceDto, RegionConstants.WSCNJ);
                replaceList.add(materialReplace);
                completeEntryResumeData(materialReplace, resumeList, currentUser, RegionConstants.WSCNJ);
            }
            if (StringUtils.isNotEmpty(materialReplaceDto.getRegionThree())) {
                MaterialReplace materialReplace = completeEntryReplaceData(materialReplaceDto, RegionConstants.SWTNJ);
                replaceList.add(materialReplace);
                completeEntryResumeData(materialReplace, resumeList, currentUser, RegionConstants.SWTNJ);
            }
        }
        if (!resumeList.isEmpty()) {
            materialResumeDao.batchAddResume(resumeList);
            materialReplaceDao.insertBatch(replaceList);
        }
        ImportResp resp = new ImportResp();
        resp.setFailedList(failedList);
        resp.setRetCode(failedList.size() > 0 ?
                ReturnCodes.HTTP_IMPORT_PART_FAIL.getRetCode() : ReturnCodes.HTTP_SUCCESS.getRetCode());
        resp.setRetMessage("导入物料替换信息成功");
        return resp;
    }

    private MaterialReplace completeEntryReplaceData(MaterialReplaceImportDto materialReplaceDto, String region) {
        MaterialReplace materialReplace = new MaterialReplace();
        String id = SnowFlake.nextIdStr();
        materialReplace.setId(id);
        materialReplace.setCompatibility(materialReplaceDto.getCompatibility());
        materialReplace.setTargetMaterial(materialReplaceDto.getTargetMaterial());
        materialReplace.setReplaceMaterial(materialReplaceDto.getReplaceMaterial());
        materialReplace.setEcn(materialReplaceDto.getEcn());
        materialReplace.setRegion(region);
        return materialReplace;

    }

    private List<MaterialResume> completeEntryResumeData(MaterialReplace materialReplace, List<MaterialResume> resumeList,
                                                         User currentUser, String region) {

        String targetMaterial = materialReplace.getTargetMaterial();
        if (targetMaterial.trim().contains(",")) {
            String[] materials = targetMaterial.trim().split(",");
            for (String materialNo : materials) {
                MaterialResume mr = new MaterialResume();
                mr.setId(SnowFlake.nextIdStr());
                mr.setSourceId(materialReplace.getId());
                mr.setMaterialNo(materialNo);
                mr.setOperateUser(currentUser.getId());
                mr.setOperateType(MaterialResumeTypeEnum.REPLACE_CHANGE.getValue());
                mr.setOperateTime(TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS));
                mr.setContent("物料替换");
                mr.setRegion(region);
                resumeList.add(mr);
            }
        } else {
            MaterialResume mr = new MaterialResume();
            mr.setId(SnowFlake.nextIdStr());
            mr.setSourceId(materialReplace.getId());
            mr.setMaterialNo(targetMaterial);
            mr.setOperateUser(currentUser.getId());
            mr.setOperateType(MaterialResumeTypeEnum.REPLACE_CHANGE.getValue());
            mr.setOperateTime(TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS));
            mr.setContent("物料替换");
            mr.setRegion(region);
            resumeList.add(mr);
        }
        return resumeList;
    }

    @Override
    public ImportResp importReplaces(String fileName) {
        String filePath = fileName;
        return excelImportService.excelFile(filePath, 2, new ExcelImportCallBack() {
            @Override
            public Collection<RowError> checkRow(String[] record) {
                return checkRecordValid(record);
            }

            @Override
            public boolean persistRowToDb(String[] record) {
                MaterialReplaceImportDto materialReplace = covertToBean(record);
                return false;
//				try {
//					materialReplaceDao.insert(mocDetail);
//					return true;
//				} catch (Exception e) {
//					return false;
//				}
            }

            @Override
            public ImportResp partFailure(ImportResp resp) {
                resp.setRetMessage("导入物料替换数据部分失败，总数=" + resp.getTotal() + ",失败总数=" + resp.getFailedTotal());
                return resp;
            }

            @Override
            public ImportResp allSuccess(ImportResp resp) {
                resp.setRetMessage("导入物料替换数据全部成功，总数=" + resp.getTotal());
                return resp;
            }

            @Override
            public List<Map> convertFailList(List<String[]> failRecords) {
                List<Map> list = new ArrayList<>();
                int sort = 1;
                for (String[] failRecord : failRecords) {
                    Map item = new HashMap();
                    item.put("sort", sort);
                    item.put("targetMaterial", failRecord[1].trim());
                    item.put("replaceMaterial", failRecord[2].trim());
                    item.put("compatibility", StringUtils.equals(failRecord[3].trim(), "是") ? 1 : 2);
                    item.put("ecn", failRecord[4].trim());
                    item.put("regionOne", failRecord[5]);
                    item.put("regionTwo", failRecord[6]);
                    item.put("regionThree", failRecord[7]);
                    list.add(item);
                    sort++;
                }
                return list;
            }

        });
    }

    /**
     * 转换数据为入库数据
     *
     * @param record 数据记录
     * @return 入库数据
     */
    private MaterialReplaceImportDto covertToBean(String[] record) {
        MaterialReplaceImportDto materialReplace = new MaterialReplaceImportDto();
        materialReplace.setTargetMaterial(record[1].trim());
        materialReplace.setReplaceMaterial(record[2].trim());
        materialReplace.setCompatibility(StringUtils.equals(record[3].trim(), "是") ? 1 : 2);
        materialReplace.setEcn(record[4].trim());
        materialReplace.setRegionOne(record[5].trim());
        materialReplace.setRegionTwo(record[6].trim());
        materialReplace.setRegionThree(record[7].trim());
        return materialReplace;

    }

    /**
     * 校验参数合法性
     *
     * @param record 导入数据
     * @return 参数合法性
     */
    private Collection<RowError> checkRecordValid(String[] record) {
        List<RowError> rowErrors = new ArrayList<>();
        if (StringUtils.isEmpty(record[1].trim())) {
            addRowError("被替换物料不能为空", rowErrors);
        } else {
            if (record[1].trim().length() > 500) {
                addRowError("物料号长度不能超过500", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[2].trim())) {
            addRowError("新物料不能为空", rowErrors);
        } else {
            if (record[2].trim().length() > 500) {
                addRowError("新物料号长度不能超过500", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[3].trim())) {
            addRowError("兼容性不能为空", rowErrors);
        } else {
            String com = record[3].trim();
            if (!StringUtils.equals(com, "是") && !StringUtils.equals(com, "否")) {
                addRowError("兼容性字段非法", rowErrors);
            }
        }
        if (StringUtils.isEmpty(record[4].trim())) {
            addRowError("ECN号不能为空", rowErrors);
        } else {
            if (record[4].trim().length() > 20) {
                addRowError("ECN号长度不能超过20", rowErrors);
            }
        }

        return rowErrors;
    }

    /**
     * 添加错误行数据
     *
     * @param errorMessage 错误信息
     * @param rowErrors    错误行数据
     */
    private void addRowError(String errorMessage, List<RowError> rowErrors) {
        RowError rowError = new RowError(errorMessage);
        rowErrors.add(rowError);
    }

    /**
     * 补全数据
     *
     * @param originList 原始数据
     * @param startNum   起始数
     * @return 补全数据列表
     */
    private List<Map<String, Object>> completeResult(List<MaterialReplace> originList, int startNum) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        if (ObjectUtil.isEmpty(originList)) {
            return resultList;
        }
        List<String> wpcMaterialList = new ArrayList<>();
        List<String> wscMaterialList = new ArrayList<>();
        List<String> swtMaterialList = new ArrayList<>();
        for (MaterialReplace replace : originList) {
            if (StringUtils.equals(replace.getRegion(), RegionConstants.WPCNJ)) {
                wpcMaterialList.add(replace.getReplaceMaterial());
                wpcMaterialList.add(replace.getTargetMaterial());
            } else if (StringUtils.equals(replace.getRegion(), RegionConstants.WSCNJ)) {
                wscMaterialList.add(replace.getReplaceMaterial());
                wscMaterialList.add(replace.getTargetMaterial());
            } else if (StringUtils.equals(replace.getRegion(), RegionConstants.SWTNJ)) {
                swtMaterialList.add(replace.getReplaceMaterial());
                swtMaterialList.add(replace.getTargetMaterial());
            }
        }
        Map<String, Map<String, Object>> wpcMap = new HashMap<>();
        Map<String, Map<String, Object>> wscMap = new HashMap<>();
        Map<String, Map<String, Object>> swtMap = new HashMap<>();
        if (wpcMaterialList.size() > 0) {
            wpcMap = syncService.getMaterials(wpcMaterialList, RegionConstants.WPCNJ);
        }
        if (wscMaterialList.size() > 0) {
            wscMap = syncService.getMaterials(wscMaterialList, RegionConstants.WSCNJ);
        }
        if (swtMaterialList.size() > 0) {
            swtMap = syncService.getMaterials(swtMaterialList, RegionConstants.SWTNJ);
        }

        int sort = startNum + 1;
        for (MaterialReplace replace : originList) {
            Map<String, Object> map = ObjectUtils.object2Map(replace);
            map.put("sort", sort);
            map.put("compatibilityName", replace.getCompatibility() == 1 ? "兼容" : "不兼容");
            Map<String, Map<String, Object>> descMap;
            if (StringUtils.equals(RegionConstants.WPCNJ, replace.getRegion())) {
                descMap = wpcMap;
            } else if (StringUtils.equals(RegionConstants.WSCNJ, replace.getRegion())) {
                descMap = wscMap;
            } else {
                descMap = swtMap;
            }
            map.put("targetMaterialDesc", descMap.containsKey(replace.getTargetMaterial()) ?
                    descMap.get(replace.getTargetMaterial()).get("pt_desc1") : null);
            if (descMap.containsKey(replace.getReplaceMaterial())) {
                map.put("replaceMaterialDesc", descMap.containsKey(replace.getReplaceMaterial()) ?
                        descMap.get(replace.getReplaceMaterial()).get("pt_desc1") : null);
            }

            resultList.add(map);
            sort++;
        }
        return resultList;
    }
}
